Skip to content

chore: release v2.2.0 - #33

Merged
Ttimmahlax merged 1 commit into
mainfrom
release-plz-2026-09-10T22-44-43Z
Sep 10, 2026
Merged

chore: release v2.2.0#33
Ttimmahlax merged 1 commit into
mainfrom
release-plz-2026-09-10T22-44-43Z

Conversation

@github-actions

@github-actions github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

🤖 New release

  • rusty_alloc: 2.1.0 -> 2.2.0 (✓ API compatible changes)
  • rusty_alloc-api: 2.1.0 -> 2.2.0
Changelog

rusty_alloc

2.2.0 - 2026-09-10

Added

  • (options) a reachable collect heartbeat, and name the pointer-width route boundary

Fixed

  • (page) derive the extend bound from the geometry, not a 64 KiB literal

Other

  • the extend fix, measured on silicon
  • (prim) derive the boundary coincidence instead of asserting it

Fixed

  • The small profile extended every page ONE BLOCK AT A TIME, so 100 % of
    allocations took the slow path.
    page_extend bounds its batch at 4 KiB of
    payload and computed that bound with a hardcoded shift whose constant term is
    really SEGMENT_SLICE_SIZE / 4096. At the shipped 64 KiB slice the literal
    was right; under --cfg ra_small_profile the slice is 4 KiB, so the bound
    was 256 bytes instead of 4 KiB — sixteen times too small. For a 512-byte
    class the batch computed to 0 and was clamped to 1, leaving every page with
    capacity == 1 and no second block for the fast path to find. Counted over
    100,000 alloc+free pairs at the small profile, entries into malloc_generic
    per op: 512 B 1.0000 -> 0.1250, 513 B 1.0000 -> 0.1667, 1 KiB 1.0000 ->
    0.2500
    , with page carve-and-retire churn falling from 195 per 100,000 to
    24/32/49. On a 32-bit host the 512-vs-513 step inverts from +8.6 % (slower)
    to −36 % (faster), about 1.9× faster at 512. Measured on silicon too
    — a XIAO ESP32-S3, main against the fix on one board with identical
    checksums and floor: 13.0 % faster on 32 B ping-pong, 15.7 % on a
    64-block mixed batch, 15.3 % on 8-512 B churn, and 1.1 % at 2,048 B,
    which is on the bin route this does not touch. Found by the Kairos RTOS
    report (docs/plans/finished/fixed-prim-small-step.md §8.7).
    The default geometry is unchanged — the derived constant equals the old
    literal there, and the all-features x86-64 assembly diff moves no executable
    function.

Added

  • --cfg ra_generic_collect="64" | "4096" | "65536", so a bare-metal
    firmware can move the periodic-collect heartbeat. It is the only lever over a
    real trade — a sweep returns an empty page, and the next allocation of that
    class carves and extends a fresh one, so a short period costs page churn
    while a long one costs capacity — and it was unreachable: options::set is a
    no-op under ONE_REGION, and the option's own doc told firmwares to "change
    the default it is built with" when no cfg existed. The default does not move.
  • prim::fixed::shape_of(size) -> Shape — page bytes, dedicated segments
    and direct_route, const and derived from the active geometry. Answers
    "which page kind, and how many region bytes, does this size cost", which
    region_stats() cannot because it reports over region extents.
    Shape::direct_route names a boundary that moves with POINTER WIDTH:
    SMALL_SIZE_MAX is 128 * size_of::<usize>(), so it is 1,024 on a 64-bit
    host and 512 on a 32-bit chip. The Kairos RTOS measured a 16 % step there on
    a device and could not reproduce it on a workstation for exactly that reason
    (docs/plans/finished/fixed-prim-small-step.md).

rusty_alloc-api

2.1.0 - 2026-09-10

Other

  • release v2.1.0


This PR was generated with release-plz.

@github-actions
github-actions Bot force-pushed the release-plz-2026-09-10T22-44-43Z branch from 919a1e5 to 2093479 Compare September 10, 2026 22:59
A minor: adds public items and moves none, and cargo-semver-checks agrees.

Added since 2.1.0:
- `--cfg ra_generic_collect`, so a bare-metal firmware can move the periodic
  collect heartbeat. `options::set` is a no-op under ONE_REGION, so this was
  the one lever over a real trade that a firmware could not reach.
- `prim::fixed::shape_of(size) -> Shape` -- page bytes, dedicated segments and
  `direct_route`, all const. `direct_route` names a boundary that moves with
  POINTER WIDTH (`SMALL_SIZE_MAX` is `128 * size_of::<usize>()`), which is why
  a sweep can look flat on a workstation and step on a 32-bit device.

Fixed, and it is the largest embedded speed change in this series:
- Under `--cfg ra_small_profile` every page was extended ONE BLOCK AT A TIME.
  `page_extend`'s 4 KiB payload bound used a hardcoded shift whose constant is
  really SEGMENT_SLICE_SIZE/4096 -- right at the 64 KiB slice, sixteen times
  too small at the small profile's 4 KiB one. A 512 B class computed a batch of
  0, clamped to 1, so every page carried capacity == 1 and `malloc_generic` ran
  on 100% of allocations. Counted: generic/op 1.0000 -> 0.1250 at 512 B. On a
  XIAO ESP32-S3, one board and one session with identical checksums: 13-16%
  faster on every binned workload. Default geometry byte-identical.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Ttimmahlax
Ttimmahlax force-pushed the release-plz-2026-09-10T22-44-43Z branch from 2093479 to db68561 Compare September 10, 2026 23:01
@Ttimmahlax
Ttimmahlax merged commit 36c3abc into main Sep 10, 2026
10 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants